/*
* Copyright 2009 NOR_/D Labs <http://labs.nortd.com>
*
* This file is part of SceneExpression.
* SceneExpression is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License 
* as published by the Free Software Foundation, either version 3 of 
* the License, or (at your option) any later version. For details
* see <http://www.gnu.org/licenses/>.
*
* * *
* 
*/

#ifndef SX_SHAPE
#define SX_SHAPE


#include <osgDB/ReadFile>
#include <osgUtil/Tessellator>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/ShapeDrawable>
#include <osg/LineWidth>

#include <sx/Node.h>

namespace sx {


class Shape: public Node {

    public:

        Shape();
                    
        void setMode( GLenum mode );
        // mode is one of the following
        // osg::PrimitiveSet::POINTS  or  GL_POINTS
        // osg::PrimitiveSet::LINES  or  GL_LINES
        // osg::PrimitiveSet::LINE_STRIP  or  GL_LINE_STRIP
        // osg::PrimitiveSet::LINE_LOOP  or  GL_LINE_LOOP
        // osg::PrimitiveSet::TRIANGLES  or  GL_TRIANGLES
        // osg::PrimitiveSet::TRIANGLE_STRIP  or  GL_TRIANGLE_STRIP
        // osg::PrimitiveSet::TRIANGLE_FAN  or  GL_TRIANGLE_FAN
        // osg::PrimitiveSet::QUADS  or  GL_QUADS, 
        // osg::PrimitiveSet::QUAD_STRIP  or  GL_QUAD_STRIP
        // osg::PrimitiveSet::POLYGON  or  GL_POLYGON         
                
        void addVertex( float x, float y, float z );
        void addVertex(osg::Vec3 vec);
        void clearVertices(); 
        
        // Once you start adding colors you are switiching to per-vertex mode.
        // This also means you need to have exactly one color per vertex.                      
        void addVertexColor( float r, float g, float b, float a );
        void addVertexColor( osg::Vec4 colorvec );
        void setColor( float r, float g, float b, float a );
        void setColor( osg::Vec4 color );

        // Once you start adding normals you are switiching to per-vertex mode.
        // This also means you need to have exactly one normal per vertex.
        void addVertexNormal( float x, float y, float z );
        void addVertexNormal( osg::Vec3 normal );
        void setNormal( float x, float y, float z );
        void setNormal( osg::Vec3 normal );
        
        void tesselate();
        
    
    protected:
      
        osg::ref_ptr<osg::Geometry>    _geometry;
        osg::ref_ptr<osg::Vec3Array>   _vertices;
        osg::ref_ptr<osg::DrawArrays>  _drawArray;
        osg::ref_ptr<osg::Vec4Array>   _colors;
        osg::ref_ptr<osg::Vec3Array>   _normals;
        
        bool bPerVertexColorBindingActive;
        bool bPerVertexNormalBindingActive;
          
        osg::ref_ptr<osgUtil::Tessellator> _tesselator;
    
};




// Primitive Shapes
//
//
class BoxShape: public Node {

    public:
        osg::ref_ptr<osg::ShapeDrawable> shapeGeometry;
          

        BoxShape() {
            shapeGeometry = new osg::ShapeDrawable(new osg::Box( osg::Vec3(0,0,0), 100.f));  
            _geode->addDrawable( shapeGeometry.get() );      
        }
        
        
        virtual osg::ref_ptr<osg::Drawable>  getOsgDrawable() {
            return shapeGeometry;
        }    
    
};

class Shape2D: public Shape {
    public:
    
        Shape2D();
                    
        void setPosition( float x, float y, float z=0.0f);
        using Node::setPosition;
                            
        void setFill( bool bFill );


    protected:
        bool  _bFill;
};




class ImageShape: public Shape {
    public:
    
        ImageShape();
                
        float getWidth();
        float getHeight();
            
        void loadImage( std::string filename );        
                

    protected:
        osg::ref_ptr<osg::Image>     _image;
        osg::ref_ptr<osg::Texture2D> _texture;
        osg::ref_ptr<osg::Vec2Array> _texcoords;
        
        void addTextureCoordinate( float u, float v );
        void addTextureCoordinate( osg::Vec2 texcoord );        
};




class TriangleShape: public Shape2D {

    public:

        TriangleShape( float a1, float a2, float b1, float b2, float c1, float c2 );                
        void setVertices( float a1, float a2, float b1, float b2, float c1, float c2 );
};


class RectangleShape: public Shape2D {

    public:

        RectangleShape( float width, float height );        
        
        void setWidth( float width );
        float getWidth() { return _width; }
        void setHeight( float height );        
        float getHeight() { return _height; }
    
    
    protected:
        float _width;
        float _height;
    
};


class EllipseShape: public Shape2D {

    public:

        EllipseShape( float width, float height );
        
        void setResolution( int res );
        int getResolution();
        void setWidth( float width );
        float getWidth() { return _width; }
        void setHeight( float height );
        float getHeight() { return _height; }
    
    protected:
        float _width;
        float _height;
        int _resolution;
    
};


class LineShape: public Shape2D {

    public:

        LineShape();                
        // void addVertex( float x, float y, float z );
        void setLineWidth( float width );
        float getLineWidth();
        
    protected:
        float _lineWidth;
};


class MonsterShape: public Shape2D {

    public:

        MonsterShape();        
        ~MonsterShape();
        
        void setColor( float r, float g, float b, float a );
        void setColor( osg::Vec4 color );
    
    protected:
        Shape* _mouthpoints;
        Shape* _leyepoints;
        Shape* _reyepoints;
    
};


}
#endif